<?php

namespace App\Models\Traits;

use App\Jobs\MakeGoldRecordJob;
use Carbon\Carbon;
use App\Models\GoldRecord;
use App\Models\GoldProduct;
use Brick\Math\RoundingMode;
use App\Jobs\CloseUnpaidStormJob;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

trait HasUserStormUnpaidCache
{
	public static function sUnpaidRecordsCacheKey($uid): string
	{
		return "user_{$uid}_unpaid_gold_records";
	}

	public static function sNewRecordCacheId($uid, $goldProductCacheId): string
	{
		$cid = $goldProductCacheId;

		$date = Carbon::today()->format('Ymd');
		$rid = (int)Redis::hGet($cid, 'gold_round_id');
		$pid = (int)Redis::hGet($cid, 'id');

		return "{$uid}_{$date}_{$rid}_{$pid}";
	}

	public static function sAddRecordToUnpaidCache($uid, $goldProductCacheId)
	{
		$cachedPid = $goldProductCacheId;
		$newCacheId = self::sNewRecordCacheId($uid, $cachedPid);

		$round = (int)Redis::hGet($cachedPid, 'round') + 1;
		$allRounds = (int)Redis::hGet($cachedPid, 'all_rounds');

		$data = [
			'cid' => $newCacheId,
			'user_id' => $uid,
			'gold_round_id' => (int)Redis::hGet($cachedPid, 'gold_round_id'),
			'gold_product_id' => (int)Redis::hGet($cachedPid, 'id'),
			'gold_record_id' => 0,
			'record_all_price' => Redis::hGet($cachedPid, 'all_price_today'),
			'pay_net_price' => Redis::hGet($cachedPid, 'net_price_today'),
			'pay_cash_price' => Redis::hGet($cachedPid, 'cash_price_today'),
			'pay_gold_beans' => Redis::hGet($cachedPid, 'gold_beans_today'),
			'gold_product_is_last_round' => $round >= $allRounds,
			'gold_product_all_price_next' => Redis::hGet($cachedPid, 'all_price_next'),
			'product_title' => Redis::hGet($cachedPid, 'product_title'),
			'product_cover' => Redis::hGet($cachedPid, 'product_cover'),
			'to_resell_applied_at' => null,
			'to_split_applied_at' => null,
			'to_take_applied_at' => null,
			'has_applied_to_resell' => false,
			'has_applied_to_split' => false,
			'has_applied_to_take' => false,
			'splits_all_count' => Redis::hGet($cachedPid, 'splits_all_count'),
			'splits_all_money' => Redis::hGet($cachedPid, 'splits_all_money'),
			'is_paying' => false,
			'is_paid' => false,
            'is_record_making' => true,
            'is_record_made' => false,
			'is_resell_applying' => false,
			'is_split_applying' => false,
			'is_take_applying' => false,
			'created_at' => Carbon::now()->toDateTimeString(),
		];

		Redis::zAdd(self::sUnpaidRecordsCacheKey($uid), 1, $newCacheId);
		Redis::hMset($newCacheId, $data);

        $queue = app()->environment('local') ? 'default' : 'make_gold_record';
        dispatch(new MakeGoldRecordJob($uid, $newCacheId))->onQueue($queue);

		$queue = app()->environment('local') ? 'default' : 'close_gold_record';
		dispatch(new CloseUnpaidStormJob($uid, $newCacheId))->onQueue($queue);
	}

    public function markRecordCacheAsMade(GoldRecord $record)
    {
        if ($record->user->is_mock) return;

        $cacheId = $record->cacheKey();

        Redis::hMset($cacheId, [
            'gold_record_id' => $record->id,
            'is_record_making' => false,
            'is_record_made' => true,
        ]);
    }


	/*==================================================================================================================*/



	public function unpaidRecordsCacheKey(): string
	{
		return self::sUnpaidRecordsCacheKey($this->id);
	}

	public function closeRecordFromUnpaidCache($unpaidCacheId)
	{
		Log::debug("Close unpaid cache id: {$unpaidCacheId}");

		Redis::transaction(function () use ($unpaidCacheId) {
			$rid = Redis::hGet($unpaidCacheId, 'gold_round_id');
			$pid = Redis::hGet($unpaidCacheId, 'gold_product_id');
			GoldProduct::sDelFromSoldCache($pid, $rid);
			GoldProduct::sAddToAliveCache($pid, $rid);
			$this->delRecordFromUnpaidCache($unpaidCacheId);
			$this->delMyRecordCache($unpaidCacheId);

			Log::debug("Unpaid record cache: {$unpaidCacheId} closed");
		});
	}

	public function markRecordPayCachePaying($cacheId)
	{
		Redis::hMset($cacheId, ['is_paying' => true, 'is_paid' => false]);
	}

	public function markRecordCacheAsPaid(GoldRecord $record)
	{
		if ($record->user->is_mock) return;

		Redis::transaction(function () use ($record) {
			$cacheId = $record->cacheKey();
			$this->addRecordToPendingCache($cacheId);
			$this->delRecordFromUnpaidCache($cacheId);
			Redis::hMset($cacheId, [
				'gold_record_id' => $record->id,
				'is_paying' => false,
				'is_paid' => true,
			]);
			Log::debug("Unpaid record cache: {$cacheId} paid");
		});
	}

	public function delRecordFromUnpaidCache($cacheId)
	{
		Redis::zRem($this->unpaidRecordsCacheKey(), $cacheId);
	}

	public function isRecordInUnpaidCache($cacheId): bool
	{
		return Redis::zScore($this->unpaidRecordsCacheKey(), $cacheId) == 1;
	}

	public function myUnpaidRecordsAllPrice()
	{
		$records = $this->myRecordsCache('unpaid');
		if ($records->isEmpty()) return 0;
		$money = big_decimal($records->sum('record_all_price'));
		return $money->toScale(2, RoundingMode::HALF_UP);
	}

	public function myUnpaidRecordsNetPrice()
	{
		$records = $this->myRecordsCache('unpaid');
		if ($records->isEmpty()) return 0;
		$money = big_decimal($records->sum('pay_net_price'));
		return $money->toScale(2, RoundingMode::HALF_UP);
	}

	public function myUnpaidRecordsCashPrice()
	{
		$records = $this->myRecordsCache('unpaid');
		if ($records->isEmpty()) return 0;
		$money = big_decimal($records->sum('pay_cash_price'));
		return $money->toScale(2, RoundingMode::HALF_UP);
	}

    public function myUnpaidRecordsBeans()
    {
        $records = $this->myRecordsCache('unpaid');
        if ($records->isEmpty()) return 0;
        $beans = big_decimal($records->sum('pay_gold_beans'));
        return $beans->toScale(2, RoundingMode::HALF_UP);
    }
}
